/*
Copyright (C) 2008 raohmaru <http://www.raohmaru.com>

This file is part of Raohmaru AS3 Framework.

Raohmaru AS3 Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Raohmaru AS3 Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Raohmaru AS3 Framework.  If not, see <http://www.gnu.org/licenses/>.
*/

package jp.raohmaru.geom 
{
import flash.geom.ColorTransform;

/**
 * La clase ColorRGB amplía la clase ColorTransform de Flash Player, e incorpora la capacidad de controlar la tinta, el brillo, el contrase, obtener el valor
 * de los componentes RGB y desplazar el valor de los mismos.
 * @author raohmaru
 * @version 1.1
 */
public class ColorRGB extends ColorTransform
{
	private var _r : int = 0,
				_g : int = 0,
				_b : int = 0,
				_tintMultiplier : Number = 0,
				_brightness : Number = 0,				_contrast : Number = 0;
	
	/**
	* Define o obtiene el valor del canal rojo (de 0 a 255).
	* Cuando define esta propiedad, cambia en consecuencia el valor desplazamiento de color <code>redOffset</code> y el valor de multiplicador de color
	* <code>redMultiplier</code>.
	*/
	public function get r() : int
	{
		return (_r < -255) ? -255 : ((_r > 255) ? 255 : _r);
	}	
	public function set r(value : int) : void
	{
		_r = value;
		
		redMultiplier = 1 - _tintMultiplier + (_contrast - _contrast*_tintMultiplier);
		redOffset = value * _tintMultiplier + Math.round((_contrast - _contrast*_tintMultiplier)*-128);
	}
	
	/**
	* Define o obtiene el valor del canal verde (de 0 a 255).
	* Cuando define esta propiedad, cambia en consecuencia el valor desplazamiento de color <code>greenOffset</code> y el valor de multiplicador de color
	* <code>greenMultiplier</code>.
	*/
	public function get g() : int
	{
		return (_g < -255) ? -255 : ((_g > 255) ? 255 : _g);
	}	
	public function set g(value : int) : void
	{
		_g = value;
		
		greenMultiplier = 1 - _tintMultiplier + (_contrast - _contrast*_tintMultiplier);
		greenOffset = value * _tintMultiplier + Math.round((_contrast - _contrast*_tintMultiplier)*-128);
	}
	
	/**
	* Define o obtiene el valor del canal azul (de 0 a 255).
	* Cuando define esta propiedad, cambia en consecuencia el valor desplazamiento de color <code>blueOffset</code> y el valor de multiplicador de color
	* <code>blueMultiplier</code>.
	*/
	public function get b() : int
	{
		return (_b < -255) ? -255 : ((_b > 255) ? 255 : _b);
	}	
	public function set b(value : int) : void
	{
		_b = value;
		
		blueMultiplier  = 1 - _tintMultiplier + (_contrast - _contrast*_tintMultiplier);
		blueOffset = value * _tintMultiplier + Math.round((_contrast - _contrast*_tintMultiplier)*-128);
	}
	
	/**
	 * Porcentaje que se aplica al color de la tinta, expresado como valor decimal entre 0 y 1. Cuando <code>tintMultiplier = 0</code>, el objeto de destino mantiene su color original
	 * y no se puede ver ningún color de tinta. Cuando <code>tintMultiplier = 1</code>, el objeto de destino se colorea por completo y no se puede ver su color original.<br><br>
	 * Esta propiedad no modifica los valores RGB.
	 * @default 0 
	 * @example
	<listing version="3.0">
	import jp.raohmaru.utils.types.ColorRGB;
	
	var color : ColorRGB = new ColorRGB(0xFFCC00);
		color.tintMultiplier = 1;
		
	some_mc.transform.colorTransform = color;
	</listing>
	 */
	public function get tintMultiplier() : Number
	{
		return _tintMultiplier;
	}	
	public function set tintMultiplier(value : Number) : void
	{
		if(value < 0) value = 0;
		if(value > 1) value = 1;
		
		_tintMultiplier = value;
		
		r = r;
		g = g;
		b = b;
	}
	
	/**
	* @private
	*/
	override public function get color() : uint
	{
		return r << 16 | g << 8 | b;
	}
	/**
	* @private
	*/
	override public function set color(value : uint) : void
	{
		r = value >> 16;
		g = value >> 8 & 0xFF;
		b = value & 0xFF;
	}
	
	/**
	 * Porcentaje de brillo, expresado como número decimal entre -1 y 1. Los valores positivos iluminan el objeto y un valor de 1 convierte el objeto en un objeto
	 * totalmente blanco. Los valores negativos oscurecen el objeto y un valor de -1 convierte el objeto en un objeto totalmente negro.<br><br>
	 * Esta propiedad no modifica los valores RGB.
	 * @default 0
	 * @example
	<listing version="3.0">
	import jp.raohmaru.utils.types.ColorRGB;
	
	var color : ColorRGB = new ColorRGB(0xFFCC00);		color.brightness = 1;		color.tintMultiplier = .5;			some_mc.transform.colorTransform = color;	</listing>
	 */
	public function get brightness() : Number
	{
		return _brightness;
	}	
	public function set brightness(value : Number) : void
	{
		if(value < -1) value = -1;
		if(value > 1) value = 1;
		
		var offset : Number = Math.ceil(255*-_brightness) + Math.floor(255*value);
		r = _r + offset;
		g = _g + offset;
		b = _b + offset;
		
		_brightness = value;
	}
	
	/**
	 * Cantidad de contraste a aplicar. Los valores van desde -1 (sin contrase), 0 (normal) a 8+ (muy contrastado).<br>
	 * Esta propiedad no modifica los valores RGB.
	 * @param amount Cantidad de contraste a aplicar (-1:sin contrase, 0:normal, 8+:muy contrastado)
	 * @default 0
	 * @source Basado en caurina.transitions.properties.ColorShortcuts._contrast_set() de Zeh Fernando, Nate Chatellier y Arthur Debert <http://code.google.com/p/tweener/>
	 */
	public function get contrast() : Number
	{
		return _contrast;
	}
	public function set contrast(value : Number) : void
	{
		_contrast = value;
		
		r = r;
		g = g;
		b = b;
	}
	
	
	
	
	/**
	 * Crea un objeto ColorRGB.
	 * @param color Un valor de color en hexadecimal (p. ej. 0xFFCC00).
	 * @example
	<listing version="3.0">
	import jp.raohmaru.utils.types.ColorRGB;
	
	var color : ColorRGB = new ColorRGB(0xFFCC00);</listing>
	 */
	public function ColorRGB(color : uint = 0)
	{
		this.color = color;
	}
	
	/**
	 * Desplaza los componentes de color RGB la cantidad especificada.
	 * @param value La cantidad a desplazar
	 * @return Una referencia al objeto ColorRGB
	 * @example
	<listing version="3.0">
	import jp.raohmaru.utils.types.ColorRGB;
	
	var color : ColorRGB = new ColorRGB();
	trace(color.shift(25));  // (r=25, g=25, b=25)</listing>
	 */
	public function shift(value : int) : ColorRGB
	{
		r += value;
		g += value;
		b += value;
		
		return this;
	}
	
	/**
	 * Devuelve una copia del objeto ColorRGB en cuestión.
	 * @return La copia del objeto
	 */
	public function clone() : ColorRGB
	{
		var clone_rgb :ColorRGB = new ColorRGB(color);
			clone_rgb.brightness = _brightness;			clone_rgb.contrast = _contrast;			clone_rgb.tintMultiplier = _tintMultiplier;
		
		return clone_rgb;
	}
	
	
	/**
	 * Formatea y devuelve una cadena que describe el color RGB en hexadecimal.
	 * @return Una cadena que describe el color RGB en hexadecimal
	 * @example
	<listing version="3.0">
	import jp.raohmaru.utils.types.ColorRGB;
	
	var color : ColorRGB = new ColorRGB();		color.r = 10;
		color.g = 125;	trace(color.toHexString());  // #0a7d00</listing>
	 */
	public function toHexString() : String
	{
		var s : String = color.toString(16);
		while(s.length < 6) s = "0" + s;
		return "#" + s;
	}
	
	/**
	 * Formatea y devuelve una cadena que describe todas las propiedades <code>r</code>, <code>g</code>, y <code>b</code> objeto ColorRGB.
	 * @return Una cadena que muestra las propiedades <code>r</code>, <code>g</code>, y <code>b</code> objeto ColorRGB
	 */
	override public function toString() : String
	{
		return "(r="+r+", g="+g+", b="+b+")";
	}
}
}